#include "TLA2518_Driver.h"

#pragma region //===字段===
static sSPI_DRIVER *pADC_Drive;
static osMutexId mutex_id = NULL;
//adc转换结果
static union ADC_Data
{
	uint8_t buf[3];	//buf[2]的高四位是通道ID
	uint16_t avg;	//adc过采样平均值
} adc_data;
#pragma endregion

#pragma region //===函数===
//描述: 获得钥匙上锁后使能片选, 支持多任务访问同一个SPI接口.
static void EnableCS(void)
{
	//lock
	if (mutex_id != NULL)
	{
		osMutexWait(mutex_id, osWaitForever);
	}
	HAL_GPIO_WritePin(ADC_SPI_CS_GPIO_Port, ADC_SPI_CS_Pin, GPIO_PIN_RESET);
}
//描述: 释放片选信号并开锁, 支持多任务访问同一个SPI接口.
static void DisableCS(void)
{
	HAL_GPIO_WritePin(ADC_SPI_CS_GPIO_Port, ADC_SPI_CS_Pin, GPIO_PIN_SET);
	//unlock
	if (mutex_id != NULL)
	{
		osMutexRelease(mutex_id);
	}
}
static void WriteReg(uint32_t reg_addr, uint8_t data)
{
	uint8_t buf[3];
	buf[0] = cmd_WRITE_REG;
	buf[1] = reg_addr;
	buf[2] = data;
	EnableCS();
	SPI_Only_Tx(pADC_Drive, buf, 3);
	DisableCS();
}
static uint8_t ReadReg(uint32_t reg_addr)
{
	uint8_t buf[3];
	buf[0] = cmd_READ_REG;
	buf[1] = reg_addr;
	buf[2] = 0;
	EnableCS();
	SPI_Tx_Rx(pADC_Drive, buf, buf, 3);
	DisableCS();
	buf[0] = 0;
	buf[1] = 0;
	buf[2] = 0;
	EnableCS();
	SPI_Tx_Rx(pADC_Drive, buf, buf, 3);
	DisableCS();
	return buf[0];
}
static void ResetTLA2518(void)
{
	GeneralCfg_t dat = { .reg = 0 };
	dat.RST = 1;
	WriteReg((uint32_t)&TLA2518_Reg->general_cfg, dat.reg);
	//RST time > 5ms
	while (ReadReg((uint32_t)&TLA2518_Reg->general_cfg) != 0)
	{
		osDelay(1);
	}	
}
static void ADC_OffsetCalibration(void)
{
	GeneralCfg_t dat = { .reg = 0 };
	dat.CAL = 1;
	WriteReg((uint32_t)&TLA2518_Reg->general_cfg, dat.reg);
	while (ReadReg((uint32_t)&TLA2518_Reg->general_cfg) != 0)
	{
		osDelay(1);
	}	
}
//设置采样周期16*48 = 768 < 1ms
static void SetSampleCycle(void)
{
	OPMODE_CFG_t tsc = { 0 };
	tsc.CLK_DIV = Tsc48us;
	WriteReg((uint32_t)&TLA2518_Reg->op_mode_cfg, tsc.reg);
	OSR_Select_t osr = Sample16;
	WriteReg((uint32_t)&TLA2518_Reg->osr_cfg, osr);
}
//使能通道id回传
static void EnableChannelID(void)
{
	DataCfg_t dat = { 0 };
	dat.APPEND_STATUS = 1;
	WriteReg((uint32_t)&TLA2518_Reg->data_cfg, dat.reg);
}
static void StartADC(void)
{
	WriteReg((uint32_t)&TLA2518_Reg->auto_seq_ch_sel, 0xFF); //8个通道都参加排序
	SEQUENCE_CFG_t seq = { 0 };
	seq.SEQ_MODE = 1;	//自动序列
	seq.SEQ_START = 1;
	WriteReg((uint32_t)&TLA2518_Reg->sequence_cfg, seq.reg); //配置成自动序列并启动
}
#pragma endregion

#pragma region //===方法===
/*
********************************************************************************
 *描述: 初始化TLA2518
 ******************************************************************************/
void TLA2518_Init(void *handle/*[I]指向外设句柄*/,
	osSemaphoreId DoneSemId/*[I]SPI通讯完成信号量句柄*/,
	osMutexId MutexId/*[I]访问SPI互斥句柄*/)
{
	if (SPI_Init(&pADC_Drive, (SPI_HandleTypeDef*)handle, DoneSemId) < 0)
		return;
	mutex_id = MutexId;
	
	//复位TLA2518
	ResetTLA2518();
	//校准零偏
	ADC_OffsetCalibration();
	//设置采样周期16*48 = 768 < 1ms
	SetSampleCycle();
	//使能通道id回传
	EnableChannelID();
	//选择扫描通道,模式,启动ADC开始转换
	StartADC();
}

/*
********************************************************************************
*描述: 获得给定通道ID的adc转换结果
*返回: 16bit转换结果
*******************************************************************************/
uint16_t TLA2518_GetADC(uint8_t channel)
{
//	SystemStatus_t state;
//	state.reg = ReadReg((uint8_t)&TLA2518_Reg->system_status);
//	while (state.OSR_DONE == 0)
//	{
//		osDelay(1);
//	}
//	WriteReg((uint8_t)&TLA2518_Reg->system_status, state.reg);	//清零可读写位OSR_DONE,BOR
	while (1)
	{
		EnableCS();
		SPI_Only_Rx(pADC_Drive, adc_data.buf, 3);
		DisableCS();
		if ((adc_data.buf[2]>>4) == channel)	//通道号不对继续读adc结果
		{
			break;
		}
		osDelay(1);
	}	
	return __REVSH(adc_data.avg);
}
#pragma endregion

